﻿using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace CommonLibrary.Helpers
{
    public static class EnumsHelper
    {
        // 此处做一个dictionary，这样原则上每个enum只要反射一次就可以得到想要的值
        // key:$"{enumType}.{fieldInfo.Name}"   MaintenanceEnum.NormalRepair
        // value:Description                    一级修
        public static Dictionary<string, string> EnumsToDescriptionAttributeDictionary = new Dictionary<string, string>();

        // key:$"{enumType}.{des.Description}"  MaintenanceEnum.一级修
        // value:fieldInfo.Name                 NormalRepair
        public static Dictionary<string, string> DescriptionAttributeToEnumsDictionary = new Dictionary<string, string>();

        static EnumsHelper()
        {
        }

        public static string GetDescriptionAttribute<T>(T t) where T : struct
        {
            var enumType = t.GetType();
            if (!enumType.IsEnum) return null;
            var key = $"{enumType}.{t.ToString()}";
            if (!EnumsToDescriptionAttributeDictionary.ContainsKey(key))
            {
                var infos = enumType.GetFields();
                foreach (var fieldInfo in infos)
                {
                    var keyTmp = $"{enumType}.{fieldInfo.Name}";
                    if (EnumsToDescriptionAttributeDictionary.ContainsKey(keyTmp)) continue;
                    foreach (var attribute in fieldInfo.GetCustomAttributes(false))
                    {
                        var des = attribute as DescriptionAttribute;
                        if (des == null) continue;
                        EnumsToDescriptionAttributeDictionary.Add(keyTmp, des.Description);
                        var desDescription = $"{enumType}.{des.Description}";
                        DescriptionAttributeToEnumsDictionary.Add(desDescription, fieldInfo.Name);
                    }
                }
            }

            return EnumsToDescriptionAttributeDictionary[key];
        }

        public static List<string> GetDescriptionAttributeList<T>() where T : struct
        {
            var list = new List<string>();
            var enumType = typeof(T);
            if (!enumType.IsEnum) return null;
            foreach (var value in Enum.GetValues(enumType))
            {
                var des = GetDescriptionAttribute((T)value);
                if (string.IsNullOrEmpty(des)) continue;
                list.Add(des);
            }

            return list;
        }

        public static T Parse<T>(this string value) where T : struct
        {
            var desDescription = $"{typeof(T)}.{value}";
            if (!DescriptionAttributeToEnumsDictionary.ContainsKey(desDescription))
            {
                GetDescriptionAttributeList<T>();
            }

            var name = DescriptionAttributeToEnumsDictionary[desDescription];
            return (T)Enum.Parse(typeof(T), name);
        }
    }
}
